
//myShell.c
//Ashish Tomar
//2009/1/27
//OS -- HW1


#include <stdio.h>
#include <errno.h>
#include<stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

struct Liist
{
char *arr;
struct Liist *next;

} *head;


typedef struct Liist item;



void display(item *q)
{ 
	if(q==NULL)
{ 
	printf("\nNothing is assigned to Path Variable\n");
}
else
	{
printf("\n");
			while(q!=NULL)

			{ 
				printf("%s:",q->arr);

			q=q->next;

			}
			printf("\n");
	}


}



char** split3(char *cmdd, int n)
{
		
int i;

		char **argg = (char **)malloc((n+1) * sizeof(char *));
	for(i = 0; i < n+1; i++)
		argg[i] = (char *)malloc(4096);

		int len,k=0,l=0;
		len=strlen(cmdd);

		for(i=0;i<len;i++)
			{

					if(cmdd[i]==' '&&cmdd[i-1]!=' ')
						{
								l=0;
								k++;
						}

						if(k>=n)
						{
							break;
						}
if(cmdd[i]!=' ')
				{
					argg[k][l]=cmdd[i];
					l++;
				}	
			}

argg[n]=(char *)0;
return argg;
}

int search(item *q, char *var,char *const argss[])
{ 
	int j=0,ex=-1;
	char * path;
char *env[] = {(char*)0};
if(q==NULL)
	{ 
				printf("\nNothing is assigned to Path Variable \n");
	}
else
	{

			while(q!=NULL)
			{
				 path=(char *)malloc(4096);
	strcpy(path,q->arr);
	strcat(path,"/");
	strcat(path,var);
	strcpy(argss[0],path);
	//printf("%s",path);
				
			ex=execv(path, argss);
			//   execl( "/bin/ls", "/bin/ls",  "-l", (char *) 0);
				if(ex==-1)
				{
						q=q->next;
					continue;
				}
				else{
					j=1;
					break;
				}

					//		q=q->next;

			}
			
	}

return j;
}
  








int outDir(item *q, char *var,char *const argss[], int arglen, char * const argfo[], int argle)
{ 
	int j=0,ex=-1,t;
	int fd, fd2,fd3;
	char *env[] = {(char*)0};
	for(t=0; t<arglen-1;t++)
	{
					if (!(strcmp(argss[t],">")))
					{
							fd=open(argss[t+1],O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
							if (fd==-1)
							{
								printf("error openin file");
							}

							dup2(fd,1);
							close(fd);
					}
					if (!(strcmp(argss[t],"<")))
					{
							fd3=open(argss[t+1],O_RDONLY);
							if (fd3==-1)
							{
								printf("error openin file");
							}

							dup2(fd3,0);
							close(fd3);
					}
					if (!(strcmp(argss[t],"2>")))
					{
							fd2=open(argss[t+1],O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
							if (fd2==-1)
							{
								printf("error openin file");
							}

							dup2(fd2,2);
							close(fd);
					}

				//	dup2();

	}


if(q==NULL)
	{ 
				printf("\nNothing is assigned to Path Variable \n");
	}
else
	{

			while(q!=NULL)
			{
				char * path=(char *)malloc(4096);
	strcpy(path,q->arr);
	strcat(path,"/");
	strcat(path,var);
//	printf("%s",path);
//	printf("%s",argss[1]);
strcpy(argfo[0], path);
//ex= execl(path, path,  (char *) 0);

					ex=execv(path, argfo);
				//ex=execve (path, argss, env);
				if(ex==-1)
				{
						q=q->next;
					continue;
				}
				else{
					j=1;
					break;
				}

					//		q=q->next;

			}
			
	}
close(fd);
close(fd2);
close(fd3);
//close(0);
return j;
}











char** splitagain(char *cmdd, int n)
{
	int i;
		char **argg = (char **)malloc((n+1) * sizeof(char *));
	for(i = 0; i < n+1; i++)
		argg[i] = (char *)malloc(4096);

		int len,k=0,l=0;
		len=strlen(cmdd);
//printf("len is %d\n",len);
		for(i=0;i<len;i++)
			{

					if(cmdd[i]=' '&&cmdd[i-1]!=' ')
						{
								l=0;
								k++;
						}

						if(k>=n)
						{
							break;
						}
if(cmdd[i]!=' ')
				{
					argg[k][l]=cmdd[i];
					l++;
				}	
			}

argg[n]=(char *)0;
return argg;
}



int outDir2(item *q,char *const argsss[], int arglen, int no, int fde[],int sign)
{ 
	char *var =(char * )malloc(4096* sizeof(char));
char *cmd =(char * )malloc(4096* sizeof(char));
//	char * const argfo[];
	int argle,i=1; 
	int flag=0,flagpipe=0;
	int j=0,ex=-1,t;
	int fd, fd2,fd3,lk;
	char *env[] = {(char*)0};
	int l,p,tt=0;
	l= strlen(argsss[no]);
	for (p=0;p<l ;p++ )
	{
			if(argsss[no][p]!=' ')
					{
				if(tt=0){
				var[p]=argsss[no][p];
				}
				cmd[p]=argsss[no][p];

					}
					else
					{
						cmd[p]=argsss[no][p];
						tt=1;
					}
	}
	//printf("var is %s\n", var);
	for (p=1;p<l ;p++ )
	{
				if(argsss[no][p]!=' ' && argsss[no][p-1]== ' ')
						{
					i++;
						}
		
	}
//printf("%d i ",i);
char** argss= split3(argsss[no],i);
					char **argfo = (char **)malloc((i+1) * sizeof(char *));
	for(t = 0; t < i+1; t++)
		argfo[t] = (char *)malloc(4096);
	var=argss[0];
//	printf("argss is %s\n",argss[0] );
	fflush(stdout);
lk=0;
					for( t=0;t<i;t++)
							{
									if (!(strcmp(argss[t],">"))||!(strcmp(argss[t],"2>"))||!(strcmp(argss[t],"<")))
																	{
																			t++;
																			flag=1;
																	}
                                                             else 
									if (!(strcmp(argss[t],"|")))
																	{
																			t++;
																			flagpipe=1;
																	}
								//									else
																		//if (!(strcmp(argss[t],NULL)))
								//{
								//										printf("yes");
								//}
																	else 
																	{
										//	printf("tehhere %s arg \n",argss[t]);
																				argfo[lk]=argss[t];
																				lk++;				
																	}
							}


		//			 argss[t-1]=argu[t];
					//printf(" %s\n",argu[t]);
							
					/*		for( t=0;t<i-1;t++)
							{
					 //argss[t-1]=argu[t];
					 	printf(" argss\n");
					printf(" %s\n",argss[t]);
							}*/
				//printf(" %d words \n",i);
argfo[lk]=(char *)0;
int lm;
for(lm=lk+1;lm<i+1;lm++)
			{
argfo[lm]=(char *)0;
			}

lk++;
//printf("argfo %s here\n", argfo[0] );
fflush(stdout);
arglen =i+1;
	for(t=0; t<arglen-1;t++)
	{
					if (!(strcmp(argss[t],">")))
					{
							fd=open(argss[t+1],O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
							if (fd==-1)
							{
								printf("error openin file");
							}

							dup2(fd,1);
					}
					if (!(strcmp(argss[t],"<")))
					{
							fd3=open(argss[t+1],O_RDONLY);
							if (fd3==-1)
							{
								printf("error openin file");
							}

							dup2(fd3,0);
					}
					if (!(strcmp(argss[t],"2>")))
					{
							fd2=open(argss[t+1],O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
							if (fd2==-1)
							{
								printf("error openin file");
							}

							dup2(fd2,2);
					}

				//	dup2();

	}




/*if(sign==0)
	{
	close(fde[0]);
	dup2(fde[1],1);   
	close(fde[1]);
	}
	else{
		//close(0);
		//dup(fde[0]);
		close(fde[1]);
		if(dup2(fde[0],0) < 0 )
		{
				printf("%s:%d:%s\n",__FUNCTION__,__LINE__,strerror(errno));
                 fflush(stdout);
		}
		close(fde[0]);
		
	}
*/


if(q==NULL)
	{ 
				printf("\nNothing is assigned to Path Variable \n");
	}
else
	{

			while(q!=NULL)
			{
				char * path=(char *)malloc(4096);
	strcpy(path,q->arr);
	strcat(path,"/");
	strcat(path,var);
//	printf("%s",path);
//	printf("%s",argss[1]);
strcpy(argfo[0], path);
//ex= execl(path, path,  (char *) 0);
//ex= execl("/bin/ls", "/bin/ls",  (char *) 0);
//this is it
			ex=execv(path, argfo);



				//ex=execve (path, argss, env);
				if(ex==-1)
				{
						q=q->next;
					continue;
				}
				else{
					j=1;
					break;
				}

					//		q=q->next;

			}
			
	}

return j;
}



item* append(item **q,char *var)
{ 
						item *temp,*r, *ret;

					temp = *q;

					if(*q==NULL)

					{ temp = (item *)malloc(sizeof(item));

					temp->arr=var;

					temp->next=NULL;

					*q=temp;
					//q=&temp;
					ret =*q;

					}

					else

					{ 
						temp = *q;
							ret= *q;
					while(temp->next !=NULL)

					{ temp=temp->next;

					}

					r = (item *)malloc(sizeof(item));

					r->arr=var;

					r->next=NULL;

					temp->next=r;

					}

return ret;
}










void del (item *p,char *num)
 {
item *temp, *m, *temp2;
temp=p;
      while(temp!=NULL)
    {
      if(!(strcmp(temp->arr, num)))
       {
           if(temp==p)
           {
              p=temp->next;
			  head=p;
			  temp2 =temp;
			  temp=temp->next;
              free(temp2);
              
           }
           else
         {
           m->next=temp->next;
		   temp2 =temp;
		    temp=temp->next;
           free(temp2);
           
         }
      }else
        {
           m=temp;
          temp= temp->next;
        }

}
    
}
















char*  parse()
{
	char *commandLine=(char *)malloc(4096*(sizeof(char)));
	//char temp[4096];
	int n=4096;
	//getline (&commandLine, &n, stdin);
//scanf("%[^\n]s",&commandLine);
	gets(commandLine);
	//strcpy(temp,commandLine);
	//after getting the valid input
	//{
//	printf("you were right");
//	}
	
	return commandLine;
}












char** split(char *cmdd, int n)
{
		
int i;
		char **argg = (char **)malloc(n * sizeof(char *));
	for(i = 0; i < n; i++)
		argg[i] = (char *)malloc(4096);

		int len,k=0,l=0;
		len=strlen(cmdd);

		for(i=0;i<len;i++)
			{

					if(cmdd[i]==' '&&cmdd[i-1]!=' ')
						{
								l=0;
								k++;
						}

						if(k>=n)
						{
							break;
						}
if(cmdd[i]!=' ')
				{
					argg[k][l]=cmdd[i];
					l++;
				}	
			}
//argg=removepipe(argg,n,pipes);
return argg;
}








char** splitpipe(char *cmdd, int n,int pipes)
{
		
int i;
		char **argg = (char **)malloc(pipes+2 * sizeof(char *));
	for(i = 0; i <=pipes+1; i++)
		argg[i] = (char *)malloc(4096);

		int len,k=0,l=0;
		len=strlen(cmdd);

		for(i=0;i<len;i++)
			{
if(cmdd[i]=='|')
				{
					l=0;
								k++;
				}
				else 	if(cmdd[i]==' '&& cmdd[i-1]!=' ' && cmdd[i-1]!='|' )
						{
								argg[k][l]=cmdd[i];
					l++;
							//	l=0;
								//k++;
						}
						else if(cmdd[i] !=' ')
				{
							argg[k][l]=cmdd[i];
					l++;
				}

						if(k>=n)
						{
							break;
						}
/*if(cmdd[i]!=' ')
				{
					argg[k][l]=cmdd[i];
					l++;
				}	*/
			}
//argg=removepipe(argg,n,pipes);
argg[pipes+1]=(char *)0;
return argg;
}







				







char** split2(char *cmdd, int n)
{
		
int i,fs=0;
		char **argg = (char **)malloc(n * sizeof(char *));
	for(i = 0; i < n-1; i++)
		argg[i] = (char *)malloc(4096);

		int len,k=-1,l=0;
		len=strlen(cmdd);

		for(i=0;i<len;i++)
			{

					if(cmdd[i]==' '&&cmdd[i-1]!=' ')
						{
								fs=1;
								l=0;
								k++;
						}

						if(k>=n)
						{
							break;
						}
if(cmdd[i]!=' '&&fs==1)
				{
					argg[k][l]=cmdd[i];
					l++;
				}	
			}

return argg;
}











int main(int argc, char *argv[])
{
int cal,arglen,u,lk=0,flag=0,flagpipe=0,p,pipes=0;

	item *curr, *temp,*delcur, *temp2;
	//printf("Welcome to myshell\n");
    int uu;
  curr=NULL;
  head = NULL;
head=append(&head, ".");
	int pid;
		while (1)
		{
			int fdes[2];
					printf("\nmyshell$ ");
					lk=0;
					flag=0;flagpipe=0;
					pipes=0;
					char *cmd=parse();

					int count,i=1,t;
if(cmd[0]=='\0')
	{
	continue;
	}
	if(cmd[0]==' ' && cmd[1]=='\0')
	{
	continue;
	}

					for(count=1;cmd[count]!='\0';count++)
					{
						if (cmd[count]=='|')//new
						{
							pipes++;
						}//new
						if(cmd[count-1]==' '&&cmd[count]!=' ')
						{
							i++;
						}
					}
		cal=i;
//printf("%d", cal);
			int h;
			int sign=0;
			if(pipes>0)
			{
						char **argpipe=splitpipe(cmd, i, pipes);
						int nt;
							int fdess[2];		
					
					for (nt=0;nt<pipes+1 ;nt++ )
						{
						int fde[2];
								if(pipe(fde)==0)
				{
									//outDir2(head, argpipe, pipes+2, nt);
									//printf("this is %s\n", argpipe[nt]);


							int ppid;
																						
																						switch(ppid = fork ())
																																	{
																																					 case -1: printf ("error in fork"); break;
																																					 case 0: // child 
																																					 if(nt==pipes)
																																		{
																																						 sign=1;
																																		}
																																		 if(nt!=pipes&&nt !=0)
																																		{
																																						 sign=10;
																																		}
																																				//outDir2(head, argpipe, pipes+2, nt,fde,sign); 
																																				if(sign==0)
																																		{
																																					close(fde[0]);
																																				dup2(fde[1],1);   
																																				close(fde[1]);
																																		}
																																		else if(sign==1){
																																																   close(fdess[1]);
																																												if(dup2(fdess[0],0) < 0 )
																																												{
																																														printf("%s:%d:%s\n",__FUNCTION__,__LINE__,strerror(errno));
																																														 fflush(stdout);
																																												}
																																												close(fdess[0]);
																																									}		
																																									else if(sign==10){
																																																   close(fdess[1]);
																																												if(dup2(fdess[0],0) < 0 )
																																												{
																																														printf("%s:%d:%s\n",__FUNCTION__,__LINE__,strerror(errno));
																																														 fflush(stdout);
																																												}
																																												close(fdess[0]);
																																												fdess[0]=fde[0];
fdess[1]=fde[1];
																																												close(fde[0]);
																																				dup2(fde[1],1);   
																																				close(fde[1]);

																																									}		
					

																																						   outDir2(head, argpipe, pipes+2, nt,fde,sign);
																									 break;
																																				 default: // parent
																																			//	outDir2(head, argpipe, pipes+2, nt+1,fde,1); 
																																				// if(nt<pipes)
																																		//{
																																				//	outDir3(head, argpipe, pipes+2, nt+1,fde); 
																																		//}
																																						   waitpid(0,NULL,0);
																									
		//printf("child ha resturned\n");
              //   fflush(stdout);
																																						
																																						//   outDir2(head, argpipe, pipes+2, 1,fde,1);
																																						  // wait (0);
																																						  break; // wait for child to terminate
																													}


					}
				}
			}

			if(pipes==0)
			{
				char**	argu=split(cmd,i);

				//char**	argu=split(cmd,i);
					char **argss= split3(cmd,i);
					char **argfo = (char **)malloc((i+1) * sizeof(char *));
	for(t = 0; t < i+1; t++)
		argfo[t] = (char *)malloc(4096);
lk=0;
					for( t=0;t<i;t++)
							{
									if (!(strcmp(argss[t],">"))||!(strcmp(argss[t],"2>"))||!(strcmp(argss[t],"<")))
																	{
																			t++;
																			flag=1;
																	}
                                                             else 
									if (!(strcmp(argss[t],"|")))
																	{
																			t++;
																			flagpipe=1;
																	}
																	else
																	{
																				argfo[lk]=argss[t];
																				lk++;				
																	}
							}


		//			 argss[t-1]=argu[t];
					//printf(" %s\n",argu[t]);
							
					/*		for( t=0;t<i-1;t++)
							{
					 //argss[t-1]=argu[t];
					 	printf(" argss\n");
					printf(" %s\n",argss[t]);
							}*/
				//printf(" %d words \n",i);
argfo[lk]=(char *)0;
int lm;
for(lm=lk+1;lm<i+1;lm++)
			{
argfo[lm]=(char *)0;
			}

lk++;
cal=i;
arglen=i+1;
				if(!(strcmp(argu[0], "exit")))
					{
							printf("Thank You for using myShell \n");
							exit(0);
							break;

					}
					else
				{	
						
						int cc;
                  for(  cc=0;cc<i;cc++)
							{
					
						}

								if(!(strcmp(argu[0], "cd")))
							{
									
									int i=chdir(argu[1]);

									if(i==-1)
										{
												printf("You dont have appropriate permissions for the PATH mentioned\n");
										}
	 
							}


							else if(!(strcmp(argu[0], "path")))
							{
									
																						if(cal==1)
																									{

																									
																										display(head);

																									}
																								else if(cal==3)
																									{
																											
																														if(!(strcmp(argu[1], "+")))
																														{

																															head=append(&head, argu[2]);
																														}
																														
																														else if(!(strcmp(argu[1], "-")))
																														{

																														
																														del(head, argu[2]);
																														
																														}
																										

																									}

							}

							else
							{ 
								//this is not built in command

								//need to be searched in current dir or else in shells path variable using fork and exec

                                //need to take care of indirection and pipeline 

								//need to use open, close and dup2

								//need pipe sytem call


switch(pid = fork ())
											{
															 case -1: printf ("error in fork"); break;
															 case 0: // child 
															
															 if(flag)
														{
																					 for(uu=0;uu <cal;uu++)
																					{
																								 if (!(strcmp(argss[uu],">"))||!(strcmp(argss[uu],"2>"))||!(strcmp(argss[uu],"<")))
																								{
																								outDir(head,argu[0],argss,arglen,argfo,lk-1);
																								}
																					}
							
														
														}else
															{
																			  u=search(head,argu[0],argss);
																			 if(u==0)
																			{
																							 printf("Enter Correct Path\n");
																			}
																			else
																			{
																						//	printf("Command Found\n");
																			}
															}
             break;
														 default: // parent
														   waitpid(0,NULL,0);
														  // close(0);
														   //close(1);
																     break; // wait for child to terminate
							}



										





							}
					

				}
			}



		}

		}
